<template>
    <div class="QilinUploadImage">
        <el-upload
            ref="uploadImageRef"
            :action="ownUploadImageConifg.action || '#' "
            :headers="ownUploadImageConifg.headers || {}"
            :list-type="ownUploadImageConifg.listType || 'picture-card' "
            :auto-upload="ownUploadImageConifg.autoUpload || false "
            :limit="ownUploadImageConifg.limit || 5 "
            :drag="ownUploadImageConifg.drag ?? true "
            :file-list="ownUploadImageConifg.fileList || [] "
            :multiple="ownUploadImageConifg.multiple ?? true "
            :disabled="ownUploadImageConifg.disabled || false"
            :show-file-list="true"
            :before-upload="handleBeforeUpload"
            :before-remove="handleBeforeRemove"
            :on-success="handleSuccess"
            :on-error="handleError"
            :on-change="handleChange"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :on-exceed="handleExceed"
            :class="[
                ownUploadImageConifg.showIconImage ? 'showIconImage' : ''
            ]"
        >
            <!-- <el-icon><CameraFilled /></el-icon> -->
            <div class="QilinUploadImage-upload flex-column" v-if="!ownUploadImageConifg.showIconImage">
                <img src="https://www.qilin-web.cn/qilin/uploads/image_20250314105203.jpeg" alt="" v-if="!ownUploadImageConifg.iconfont">
                <i :class="['iconfont',ownUploadImageConifg.iconfont]" v-else></i>
                <div class="image-tip-text">上传图片</div>
            </div>
            <div class="QilinUploadImage-iconImage flex-column" v-else>
                <div class="QilinUploadImage-iconImage-text flex-row">
                    <el-icon><Upload /></el-icon>
                    <span>上传图片</span>
                </div>
                <div class="QilinUploadImage-iconImage-tip">
                    {{ownUploadImageConifg.fileSizeText || "大小20M以内"}}
                </div>
            </div>
        </el-upload>
        <span class="QilinUploadImage-tip">{{ownUploadImageConifg.fileTypeText || "(支持jpg、png、jpeg等图片格式)"}}</span>
    </div>
    <QilinDialog v-model:dialogConfig="dialogConfig" @handleClose="closeDialog">
        <el-image
            style="width:100%;height:500px;"
            :src="currentImage"
            :preview-src-list="ownUploadImageConifg.fileList.map((item)=>{
                return ((ownUploadImageConifg.imageIp || '') + item[ownUploadImageConifg.imageOptions?.serverUrl || 'fileName']);
            })"
            :initial-index="initialIndex"
            :fit="ownUploadImageConifg.imageFit || 'contain'"
        ></el-image>
    </QilinDialog>
</template>

<script setup>
import {defineOptions,ref,computed,reactive,nextTick} from "vue";
import {ElMessage} from "element-plus";
import Qilin from "qilin-utils";

defineOptions({
    name:"QilinUploadImage"
});

/*
    数据变量定义区域
*/
// 获取上传图片元素DOM
const uploadImageRef=ref(null);
// 当前预览图片url
let currentImage=ref("");
// 当前预览图片索引位置
let initialIndex=ref(0);


/*
    计算属性等代码区域
*/
// 接收来自父组件的传参
const propsValue=defineProps({
    uploadImageConfig:{
        type:Object,
        default(){
            return {
                // 组件自身的默认配置
                action:"#", //文件上传至服务器url
                headers:{}, //设置上传的请求头部--当action有值时必填，用以设置token等
                listType:"picture-card", //文件列表类型
                autoUpload:false, //是否自动上传，当action有值时，则autoUpload须为true
                limit:5, //文件允许上传数量
                fileList:[], //默认上传文件--必填
                multiple:false, //是否支持多选文件
                drag:true, //是否启用拖拽上传
                disabled:false, //是否禁用上传
                fileTypeText:"（支持png、jpg、jpeg、gif文件格式）", //支持格式文字说明
                fileType:["png","jpg","jpeg","gif"], //支持上传的文件类型
                fileSize:20 * 1000 * 1000, //文件上传大小限制20M之内默认
                fileSizeText:"大小20M以内", //文件大小提示标语
                iconfont:"icon-shangchuan-shangchuantupian", //默认的显示图标
                showIconImage:false, //是否显示图片形式的提示标识
                imageFit:"contain", //图片的适应类型--默认contain
                imageIp:"", //设置查看图片或文件的服务器ip--预览图片时须借助该属性或imageOptions属性的配置
                imageOptions:{ //图片设置配置项
                    serverOriginalName:"originalFilename", //文件上传至后端，返回的原始文件名称
                    serverName:"newFileName", //文件上传至后端，返回的文件名称--用以回显文件的名称
                    serverUrl:"fileName", //文件上传至后端，返回的文件url地址--用以回显文件的url
                    serverWholeUrl:"url", //文件上传至后端，返回的完整的文件url地址--用以回显文件的完整url
                    responseDataName:"data", //文件上传至服务器，返回的响应字段，默认为data，通常也是data
                }
            };
        }
    },
    fileList:{ //用以回显
        type:[Array,String],
        default(){
            return []
        }
    }
});
// 暴露父组件自定义方法
const emits=defineEmits(["update:uploadImageConfig","success","actionSuccess"]);
// 组件自身的配置项
let ownUploadImageConifg=computed({
    get(){
        propsValue.uploadImageConfig.fileList = propsValue.fileList ? ( typeof propsValue.fileList === "string" ? JSON.parse(propsValue.fileList) : propsValue.fileList || [] ) : [];
        return propsValue.uploadImageConfig;
    },
    set(val){
        emits("update:uploadImageConfig",val);
    }
});


/*
    逻辑脚本代码区域
*/
/**
 *  **当action为指定服务器地址时
 */
// 文件上传之前的事件监听
const handleBeforeUpload=(file)=>{
    // console.log(file,ownUploadImageConifg.value.action);
    if(!ownUploadImageConifg.value.action || ownUploadImageConifg.value.action === "#") return ;
    const index=file.name.lastIndexOf(".");
    const fileType=file.name.slice(index+1).toLowerCase();
    if(ownUploadImageConifg.value.fileType && !ownUploadImageConifg.value.fileType.includes(fileType)){
        ElMessage({
            message:"请上传符合格式要求的图片",
            type:"warning"
        });
        return false;
    }else if(!ownUploadImageConifg.value.fileType && !["png","jpg","jpeg","gif"].includes(fileType)){
        ElMessage({
            message:"请上传符合格式要求的图片",
            type:"warning"
        });
        return false;
    }else if(file.size > (ownUploadImageConifg.value.fileSize || 20 * 1000 * 1000)){
        ElMessage({
            message:"文件大小超过限制",
            type:"warning"
        });
        return false;
    };
};
// 文件上传成功后的事件监听
const handleSuccess=(response,uploadFile,uploadFiles)=>{
    // console.log(response,uploadFile,uploadFiles,"========");
    if(response[ownUploadImageConifg.value.imageOptions?.responseDataName || "data"]){
        emits("actionSuccess",response,uploadFile);
    }else{
        ElMessage({
            message:"上传失败，请检查服务器",
            type:"error"
        });
        nextTick(()=>{
            uploadImageRef.value.handleRemove(uploadFile);
        });
    }
};
// 文件上传失败后的事件监听
const handleError=(error,uploadFile,uploadFiles)=>{
    // console.log(error,uploadFile,uploadFiles,"========");
    ElMessage({
        message:"上传失败，请检查服务器",
        type:"error"
    });
    nextTick(()=>{
        uploadImageRef.value.handleRemove(uploadFile);
    });
};

/**
 *  **当action未填写时
 */
// 文件上传状态改变事件监听
const handleChange=(file)=>{
    // console.log(file);
    if(ownUploadImageConifg.value.action) return ;
    const index=file.name.lastIndexOf(".");
    const fileType=file.name.slice(index+1).toLowerCase();
    if(ownUploadImageConifg.value.fileType && !ownUploadImageConifg.value.fileType.includes(fileType)){
        ElMessage({
            message:"请上传符合格式要求的图片",
            type:"warning"
        });
        nextTick(()=>{
            uploadImageRef.value.handleRemove(file);
        });
    }else if(!ownUploadImageConifg.value.fileType && !["png","jpg","jpeg","gif"].includes(fileType)){
        ElMessage({
            message:"请上传符合格式要求的图片",
            type:"warning"
        });
        nextTick(()=>{
            uploadImageRef.value.handleRemove(file);
        });
    }else if(file.size > (ownUploadImageConifg.value.fileSize || 20 * 1000 * 1000)){
        ElMessage({
            message:"文件大小超过限制",
            type:"warning"
        });
        nextTick(()=>{
            uploadImageRef.value.handleRemove(file);
        });
    }else{
        ownUploadImageConifg.value.fileList.push({
            raw:file.raw,
            url:file.url,
            name:file.name
        });
        emits("success",ownUploadImageConifg.value.fileList,file);
    };
};
// 文件超出限制事件监听
const handleExceed=(file,files)=>{
    // console.log(file,files);
    ElMessage({
        message:"文件上传数量不能大于"+(ownUploadImageConifg.value.limit || 5)+"个",
        type:"warning"
    });
};
// 文件预览事件监听
const handlePreview=(file)=>{
    // console.log(file,ownUploadImageConifg.value.fileList,"=======");
    if(file.raw){ //若是本地上传后直接预览
        // 本地上传时可以回显图片的一般只有原文件的url字段
        currentImage.value = file[ownUploadImageConifg.value.imageOptions?.serverWholeUrl || "url"];
        // 不上传服务器形式，用户自定义上传，此时返回文件参数一般没有raw字段
        // originalFilename参数表示图片文件的原始名称，一般与原文件的name对应，
        // 具体参数名应与实际业务中后台返回字段对应，默认originalFilename
        if(!ownUploadImageConifg.value.action){ 
            initialIndex.value = ownUploadImageConifg.value.fileList.findIndex((item)=>{
                return item[ownUploadImageConifg.value.imageOptions?.originalFilename || "originalFilename"] === file.name;
            });
        }else{ //上传服务器形式
            initialIndex.value = ownUploadImageConifg.value.fileList.findIndex((item)=>{
                return item[ownUploadImageConifg.value.imageOptions?.originalFilename || "originalFilename"] === file.name;
            });
        }
    }else{ //回显预览
        // 回显预览时file文件此时应当为后台返回的文件对象
        // fileName参数表示图片文件的回显名称，具体参数名应于实际业务中后台返回字段对应，默认fileName
        // 一般需结合imageIp+fileName来显示完整url
        initialIndex.value = ownUploadImageConifg.value.fileList.findIndex((item)=>{
            return item[ownUploadImageConifg.value.imageOptions?.serverUrl || "fileName"] === file[ownUploadImageConifg.value.imageOptions?.serverUrl || "fileName"];
        });
        currentImage.value=(ownUploadImageConifg.value.imageIp || "") + file[ownUploadImageConifg.value.imageOptions?.serverUrl || "fileName"];
    };
    dialogConfig.isShow=true;
};
// 文件删除之前的事件监听
const handleBeforeRemove=(uploadFile,uploadFiles)=>{
    // console.log(uploadFile,uploadFiles,ownUploadImageConifg.value.fileList,"=======253");
    // return true;
};
// 文件删除事件监听
const handleRemove=(file,files)=>{
    // console.log(file,ownUploadImageConifg.value.fileList,files,"=======258");
    let index=-1;
    if(file.raw){ //若是本地上传后直接删除
        // 不上传服务器形式，用户自定义上传，此时返回文件参数一般没有raw字段
        // originalFilename参数表示图片文件的原始名称，一般与原文件的name对应，
        // 具体参数名应与实际业务中后台返回字段对应，默认originalFilename
        if(!ownUploadImageConifg.value.action){ 
            index=ownUploadImageConifg.value.fileList.findIndex((item)=>{
                return item[ownUploadImageConifg.value.imageOptions?.originalFilename || "originalFilename"] === file.name;
            });
        }else{//上传服务器形式
            index=ownUploadImageConifg.value.fileList.findIndex((item)=>{
                return item[ownUploadImageConifg.value.imageOptions?.originalFilename || "originalFilename"] === file.name;
            });
        }
    }else{ //回显删除--这段代码其实并不需要，框架内部在此之前已经做了删除
        // 回显预览时file文件此时应当为后台返回的文件对象
        // originalFilename参数表示图片文件的原始名称，
        // 具体参数名应于实际业务中后台返回字段对应，默认originalFilename
        index=ownUploadImageConifg.value.fileList.findIndex((item)=>{
            return item[ownUploadImageConifg.value.imageOptions?.serverOriginalName || "originalFilename"] === file[ownUploadImageConifg.value.imageOptions?.serverOriginalName || "originalFilename"];
        });
    };
    // console.log(index,"===========269");
    if(index !== -1){
        ownUploadImageConifg.value.fileList.splice(index,1);
        emits("success",ownUploadImageConifg.value.fileList,index);
    };
};
// 关闭预览弹窗事件监听
const closeDialog=()=>{
    dialogConfig.isShow=false;
};

// 图片预览弹窗配置项
let dialogConfig=reactive({
    isShow:false,
    title:"图片预览",
    isHideFooter:true
});


/*
    生命周期等代码区域
*/

</script>

<style lang="scss" scoped>
.QilinUploadImage{
    width:100%;
    :deep(.el-upload-list__item){
        width:120px;
        height:120px;
    }
    >.showIconImage{
        :deep(.el-upload.el-upload.el-upload--picture-card){
            width:140px;
            height:80px;
            border:none;
            >.el-upload-dragger{
                width:140px;
                height:80px;
                padding:15px;
                border-color:$primary-text-color;
                background-color:#FAFAFA;
            }
        }
        :deep(>.el-upload-list--picture-card){
            .el-upload-list__item{
                width:80px;
                height:80px;
                .el-icon--close-tip{
                    display:none !important;
                }
            }
        }
    }
    :deep(.el-upload){
        width:120px;
        height:120px;
        background-color:transparent;
        border:none;
        >.el-upload-dragger{
            width:120px;
            height:120px;
        }
        .QilinUploadImage-upload{
            align-items:center;
            >img{
                width:16px;
                height:16px;
            }
            >.image-tip-text{
                font-size:12px;
                margin-top:8px;
                line-height:12px;
            }
        }
        .QilinUploadImage-iconImage{
            font-size:12px;
            align-items:center;
            >.QilinUploadImage-iconImage-text{
                align-items:center;
                >img{
                    width:16px;
                    height:16px;
                }
                >span{
                    color:$text-color-65;
                    margin-left:6px;
                }
            }
            >.QilinUploadImage-iconImage-tip{
                color:$text-color-45;
                margin-top:8px;
                line-height:12px;
            }
        }
    }
    >.QilinUploadImage-tip{
        display:inline-block;
        color:$text-color-45;
        font-size:12px;
        margin-top:4px;
        line-height:12px;
    }
    >.QilinUploadImage-list{
        width:65%;
        >.qilin-QilinUploadImage-list-item{
            display:flex;
            align-items:center;
            justify-content: space-between;
            margin:10px 0;
            line-height:1;
            >img{
                width:15px;
                height:15px;
            }
            >span{
                color:$primary-text-color;
                margin:0 6px;
                cursor:pointer;
                flex:1;
                white-space:nowrap;
                overflow:hidden;
                text-overflow:ellipsis;
            }
        }
    }
}
</style>
